package gm.server.virtual.simulator2D;

import com.sun.scenario.scenegraph.SGGroup;
import com.sun.scenario.scenegraph.SGImage;
import com.sun.scenario.scenegraph.SGTransform;
import java.awt.Color;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * Kanava háttérkép.
 *
 * @author imruf84
 */
public class KanavaImage extends SGGroup {

    /**
     * Nagyítás.
     */
    private double scale = 1.0;
    /**
     * Transzformáció.
     */
    private final SGTransform.Affine transform = SGTransform.createAffine(null, null);
    /**
     * Kép.
     */
    private BufferedImage image = null;
    /**
     * Felismert lyukak képe.
     */
    private BufferedImage imageHolesFound = null;
    /**
     * Kép tárolója.
     */
    private final SGGroup imageContainer = new SGGroup();
    /**
     * Kép helye.
     */
    private String path = "";
    /**
     * Megjelölt lyukak képének tárolója.
     */
    private SGImage markedHolesImage;

    /**
     * Konstruktor.
     */
    public KanavaImage() {
    }

    /**
     * Kép megadása.
     *
     * @param path kép helye
     * @throws IOException kivétel
     */
    public void setImage(final String path) throws IOException {

        SGImage img = new SGImage();
        image = ImageIO.read(new File(path));
        img.setImage(image);
        img.setInterpolationHint(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        imageContainer.add(img);

        markedHolesImage = new SGImage();
        clearHoleMarks();
        markedHolesImage.setInterpolationHint(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        imageContainer.add(markedHolesImage);

        updateTransform();

        transform.setChild(imageContainer);
        add(transform);

        this.path = path;
    }

    /**
     * Globális koordináta lekérdezése a kép terében.
     *
     * @param p pont
     * @return pont a képtérben
     * @throws NoninvertibleTransformException kivétel
     */
    public Point getLocationAtImageSpace(Point2D p) throws NoninvertibleTransformException {
        Point2D pi = getTransform().getAffine().inverseTransform(p, null);
        return new Point(Math.round((float) pi.getX()), Math.round((float) pi.getY()));
    }

    /**
     * Megtalált pont helyének megjelölése.
     *
     * @param p pont globális koordinátái
     * @param c szín
     * @param size méret
     * @throws NoninvertibleTransformException kivétel
     */
    public void markHoleFound(Point2D p, Color c, int size) throws NoninvertibleTransformException {
        Point pp = getLocationAtImageSpace(p);
        for (int x = -size; x < size; x++) {
            for (int y = -size; y < size; y++) {
                imageHolesFound.setRGB(pp.x + x, pp.y + y, c.getRGB());
            }
        }
    }

    /**
     * Megjelölt lyukak jelöléseinek a törlése.
     */
    public void clearHoleMarks() {
        imageHolesFound = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        markedHolesImage.setImage(imageHolesFound);
    }

    /**
     * Transzformáció mátrix frissítése.
     */
    public void updateTransform() {
        AffineTransform t = new AffineTransform();
        t.scale(-1, -1);
        t.scale(scale, scale);
        if (null != image) {
            t.translate(-image.getWidth() / 2d, -image.getHeight());
        }
        transform.setAffine(t);
    }

    /**
     * Kép tárolójának a lekérdezése.
     *
     * @return kép tárolója
     */
    public SGGroup getImageContainer() {
        return imageContainer;
    }

    /**
     * Nagyítás megadása.
     *
     * @param scale nagyítás
     */
    public void setScale(double scale) {
        this.scale = scale;
    }

    /**
     * Nagyítás lekérdezése.
     *
     * @return nagyítás
     */
    public double getScale() {
        return scale;
    }

    /**
     * Fájlnév lekérdezése.
     *
     * @return fájlnév
     */
    public String getPath() {
        return this.path;
    }

    /**
     * Transzformáció lekérdezése.
     *
     * @return transzformáció
     */
    public SGTransform.Affine getTransform() {
        return transform;
    }

    /**
     * Kép lekérdezése.
     *
     * @return kép
     */
    public BufferedImage getImage() {
        return image;
    }

}
